package com.example.resolver;

import com.example.dto.AccountDto;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/*
 * 参数解析器
 * */
// 使用 @Component 注解将该类标记为 Spring 组件，使其能够被 Spring 自动扫描并管理
@Component
public class AccountHandlerMethodResolver implements HandlerMethodArgumentResolver {

    // 使用 @Autowired 注解自动注入 UserService 实例，用于调用用户信息查询服务
    @Autowired
    private UserService userService;

    /**
     * 判断当前解析器是否支持处理指定的方法参数。
     * Spring MVC 在处理请求并准备调用控制器方法时，会遍历所有注册的 HandlerMethodArgumentResolver，
     * 对控制器方法的每个参数调用此方法，以确定是否使用当前解析器来处理该参数。
     *
     * @param parameter 控制器方法的参数信息，包含参数的类型、注解等信息
     * @return 如果参数的类型是 AccountDto 或其子类，则返回 true，表示支持处理该参数；否则返回 false
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {

        // isAssignableFrom 方法用于判断 parameter 的类型是否为 AccountDto 或其子类
        return parameter.getParameterType().isAssignableFrom(AccountDto.class);
    }

    /**
     * 当 supportsParameter 方法返回 true 时，Spring MVC 会调用此方法来实际解析并赋值该参数。
     * 该方法的主要作用是从请求中获取相关数据，并根据这些数据生成参数的值。
     *
     * @param parameter     控制器方法的参数信息
     * @param mavContainer  用于存储模型和视图信息的容器，通常在视图渲染时使用
     * @param webRequest    封装了当前请求的信息，可用于获取请求的属性、参数等
     * @param binderFactory 用于创建 WebDataBinder 对象，可用于数据绑定和验证
     * @return 返回解析后的参数值，将被赋值给控制器方法的对应参数
     * @throws Exception 如果在解析过程中出现异常，将抛出异常
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        // 从请求属性中获取名为 "account" 的值，使用 RequestAttributes.SCOPE_REQUEST 表示从请求作用域中获取
        String account = (String) webRequest.getAttribute("account", RequestAttributes.SCOPE_REQUEST);
        // 调用 UserService 的 selectInfoByAccount 方法，根据账户信息查询相关数据
        return userService.selectInfoByAccount(account);
    }
}


